import { MapConfigs } from "./MapConfigs";
import { GridType, TerrainType } from "./utils/TerrainConfigManager";
import { WoundedConfigItem, WoundedConfigManager } from "./utils/WoundedConfigManager";
import { Wounded } from "./Wounded";
import { WoundedList } from "./WoundedList";

const { regClass, property } = Laya;


@regClass()
export class WoundedScript extends Laya.Script {
    declare owner: Laya.Sprite
    // --- UI组件 ---
    @property(String)
    public mapId: string = null; // 地图背景图，用于获取尺寸

    @property(Laya.Box)
    public box_map: Laya.Box = null; // 放置可拖动地形的容器

    @property(Laya.Box)
    public box_game: Laya.Box = null; // 游戏主容器，背景和格子放这里

    @property(Laya.Box)
    public box_list: Laya.Box = null; // 放置地形列表UI的容器

    @property(Laya.Button)
    public box_export: Laya.Button = null; // 导出按钮

    @property(Laya.Button)
    public box_load: Laya.Button = null; // 加载/导入按钮



    // --- 建筑/地形相关 ---
    private woundedList: WoundedList;        // 地形列表UI实例
    private selectedWounded: Wounded = null; // 当前选中的地形对象
    private draggingWounded: Wounded = null; // 当前正在拖动的地形对象

    // --- 拖拽相关 ---
    private offsetX: number = 0; // 鼠标按下时相对于地形中心点的X偏移
    private offsetY: number = 0; // 鼠标按下时相对于地形中心点的Y偏移

    // --- 地图格子 ---
    // 存储从 JSON 加载的详细格子信息 (包含 x, y, row, col, type)
    private gridData: Array<Array<GridType>> = [];

    // 地图格子状态二维数组 (用于快速查询占用状态: 0=空, -1=边界, 其他=地形type/id)
    private localMapGrid: Array<Array<GridType>> = [];
    // 用于绘制格子的容器 Sprite
    // private gridContainer: Laya.Sprite = null;
    // --- 格子配置 ---
    private readonly gridWidth: number = 50; // 格子宽度 (菱形宽度)
    private readonly gridVisualHeight: number = 25; // 菱形实际视觉高度
    private readonly gridRowSpacing: number = this.gridVisualHeight / 2; // 行间距 = 12.5


    map_width_pixels = 2048
    map_height_pixels = 2304
    /**
     * 组件被激活后执行，此时所有节点和组件均已创建完毕，此方法只执行一次
     */
    async onAwake() {
        console.log("WoundedScript onAwake started.");
        this.owner.mouseThrough = true
        console.log("WoundedScript onAwake finished.");
    }
    private loadGridData(map_id: string): void {
        const jsonPath = `configs/map/map_grid${map_id}.json`; // 确保这个路径相对于 index.html 是正确的
        console.log(`Loading grid data from: ${jsonPath}`);
        Laya.loader.load(jsonPath, Laya.Handler.create(this, (res: any) => {
            if (res && Array.isArray(res.data)) {
                this.gridData = res.data; // 存储从JSON加载的原始格子数据
                console.log(`Loaded ${this.gridData.length} grid cells from ${jsonPath}.`);


                // 绘制可视化格子
                // this.drawGrid(this.gridData);

            } else {
                console.error(`Failed to load or parse ${jsonPath}. Ensure the file exists, is valid JSON, and accessible.`);
                this.gridData = [];
                this.showTip(`错误: 无法加载地图格子数据 (${jsonPath})!`);
            }
        }), null, Laya.Loader.JSON); // 明确指定加载类型为 JSON
    }
    /**
     * 初始化Script
     * localMapGrid 建筑已经摆放好的位置
     */
    async initScript(localMapGrid: Array<Array<GridType>>, mapId: string) {
        this.mapId = mapId
        this.localMapGrid = localMapGrid;
        await WoundedConfigManager.getInstance().loadConfig(this.mapId)
        let mapConfigs = MapConfigs.getMapConfig(this.mapId)
        this.map_width_pixels = mapConfigs.size.width
        this.map_height_pixels = mapConfigs.size.height
        this.loadGridData(mapId)
        // new Laya.Scene().loadScene
        // // 1. 创建用于绘制格子的容器，并添加到游戏层底部
        // this.gridContainer = new Laya.Sprite();
        // this.gridContainer.name = "GridContainer"; // 方便调试时查找
        // if (this.box_game) {
        //     this.box_game.addChild(this.gridContainer);
        //     // 确保格子绘制在最底层，其他游戏元素（如地图背景Image_map如果也在box_game里）应该在它之上
        //     this.box_game.setChildIndex(this.gridContainer, 0);
        //     console.log("GridContainer added to box_game.");
        // } else {
        //     console.error("box_game is not assigned in the editor! Grid cannot be drawn.");
        //     // 备选方案：添加到舞台，但这可能不在预期层级
        //     // Laya.stage.addChild(this.gridContainer);
        // }

        // 2. 初始化地形列表UI
        this.initWoundedList();

        // 3. 初始化地图拖拽、导入/导出按钮事件
        this.initMapDragEvents();
    }

    /**
     * 初始化地形列表UI及事件监听
     */
    private initWoundedList(): void {
        if (!this.box_list) {
            console.error("box_list is not assigned in the editor! Cannot initialize WoundedList.");
            return;
        }
        this.woundedList = new WoundedList(); // 假设 WoundedList 构造函数或内部方法会创建UI
        this.box_list.addChild(this.woundedList);
        // 监听从 WoundedList 组件派发的 'WoundedSelected' 事件
        this.woundedList.on('WoundedSelected', this, this.onWoundedSelected);
        console.log("WoundedList initialized and added to box_list.");
    }

    /**
     * 将格子坐标 (row, col) 转换为对应格子中心的屏幕坐标 (x, y)
     * 这个计算逻辑必须与生成 JSON 时 Python 脚本的逻辑相对应，并返回中心点。
     * @param row 格子行号
     * @param col 格子列号
     * @returns 屏幕坐标对象 { x, y }，代表格子中心
     */
    private gridToScreen(row: number, col: number): { x: number, y: number } {
        const tileX_topleft = (row % 2) * (this.gridWidth / 2) + col * this.gridWidth;
        // Y 坐标基于行间距 (12.5)
        const tileY_topleft = row * this.gridRowSpacing;

        // 中心点 Y = 左上角 Y + 菱形视觉高度的一半 (12.5)
        const centerX = tileX_topleft //+ this.gridWidth / 2;
        const centerY = tileY_topleft //+ this.gridVisualHeight / 2; // 使用 12.5

        return { x: centerX, y: centerY };
    }


    /**
     * 将世界坐标转换为等角地图格子坐标
     * @param x 世界坐标X
     * @param y 世界坐标Y
     * @returns 格子坐标 {row, col}
     */
    public sceneToGrid(x: number, y: number): { row: number, col: number } {
        const adjustedY = y

        // 计算行号 (row)
        const row = Math.floor(adjustedY / this.gridRowSpacing);
        let col = -1
        if (row % 2 == 0) {
            col = Math.floor(x / (this.gridWidth));

        } else {
            col = Math.floor((x - this.gridWidth / 2) / (this.gridWidth));
        }
        // 计算列号 (col)

        return { row, col };
    }
    /**
     * 将屏幕坐标 (x, y) 转换为最近的格子坐标 (row, col)
     * 这是 gridToScreen 的逆运算，使用查找最近中心点的方法。
     * @param x 屏幕X坐标
     * @param y 屏幕Y坐标
     * @returns 最近的有效格子坐标对象 { row, col }
     */
    private screenToGridInOther(x: number, y: number): { row: number, col: number } {
        const tileW = this.gridWidth;
        const tileH = this.gridRowSpacing; // 使用行间距 12.5 进行计算
        const tileVisualH_half = this.gridVisualHeight / 2; // 菱形半高 12.5

        // 估算 row: centerY = row * tileH + tileVisualH_half => row = (y - tileVisualH_half) / tileH
        const approxRow = Math.round((y - tileVisualH_half) / tileH);
        // 估算 col: centerX = (row % 2)*(tileW/2) + col*tileW + tileW/2 => col = (x - (row%2)*(tileW/2) - tileW/2) / tileW
        const rowOffsetX = (approxRow % 2) * (tileW / 2);
        const approxCol = Math.round((x - rowOffsetX - tileW / 2) / tileW);

        // --- 精确查找最近的格子中心 ---
        let closestRow = -1;
        let closestCol = -1;
        let minDistanceSq = Infinity;

        // 搜索中心点 (approxRow, approxCol) 及其周围 3x3 的格子
        for (let rOffset = -1; rOffset <= 1; rOffset++) {
            for (let cOffset = -1; cOffset <= 1; cOffset++) {
                const testRow = approxRow + rOffset;
                const testCol = approxCol + cOffset;

                // 检查计算出的 row/col 是否在 mapGrid 的有效范围内
                if (testRow < 0 || testCol < 0 ||
                    testRow >= this.localMapGrid.length ||
                    !this.localMapGrid[testRow] || // 确保行存在
                    testCol >= this.localMapGrid[testRow].length) {
                    continue; // 超出已知地图范围或无效索引
                }

                // 计算测试格子的中心点屏幕坐标
                const testCenter = this.gridToScreen(testRow, testCol);

                // 计算屏幕点 (x, y) 到测试格子中心的距离平方
                const dx = x - testCenter.x;
                const dy = y - testCenter.y;
                const distanceSq = dx * dx + dy * dy;

                // 如果距离更近，更新最近的格子
                if (distanceSq < minDistanceSq) {
                    minDistanceSq = distanceSq;
                    closestRow = testRow;
                    closestCol = testCol;
                }
            }
        }

        // 如果经过搜索仍然没有找到有效的格子 (例如地图数据为空或点击在非常远的地方)
        if (closestRow === -1 || closestCol === -1) {
            console.warn(`Could not find valid grid cell near screen coordinates (${x.toFixed(1)}, ${y.toFixed(1)}). Returning approximate or default.`);
            // 返回一个基于粗略估计的安全值，例如限制在 (0, 0)
            const safeRow = Math.max(0, approxRow);
            const safeCol = Math.max(0, approxCol);
            // 进一步检查这个安全值是否真的在范围内
            if (safeRow < this.localMapGrid.length && this.localMapGrid[safeRow] && safeCol < this.localMapGrid[safeRow].length) {
                return { row: safeRow, col: safeCol };
            } else {
                return { row: 0, col: 0 }; // Fallback to origin if even approx is bad
            }
        }

        // 返回找到的最近的有效格子的坐标
        return { row: closestRow, col: closestCol };
    }


    /**
     * 处理键盘按下事件
     * @param e 键盘事件对象
     */
    onKeyDown(e: Laya.Event): void {
        // 如果没有选中的地形，直接返回
        if (!this.selectedWounded) return;
        let Wounded = this.selectedWounded

        let offsetX1 = this.selectedWounded.width / 2 - this.selectedWounded.width & this.selectedWounded.anchorX + 25


        let currentPos = this.sceneToGrid(this.selectedWounded.x - offsetX1, this.selectedWounded.y - 25);
        console.log("currentPos", currentPos);
        let newRow = currentPos.row;
        let newCol = currentPos.col;
        console.log(e.keyCode)
        // 根据按键移动地形
        switch (e.keyCode) {
            case 87: // W键 - 上
            case 38: // 上箭头
                newRow--;
                break;
            case 83: // S键 - 下
            case 40: // 下箭头
                newRow++;
                break;
            case 65: // A键 - 左
            case 37: // 左箭头
                newCol--;
                break;
            case 68: // D键 - 右
            case 39: // 右箭头
                newCol++;
                break;
            case 8:
                if (Wounded.parent) { // 确保它还在场景中
                    // 清除地图格子状态
                    this.clearOccupiedGridsInState(Wounded); // 确保清除的是最新的占用格子

                    // 从父节点移除并销毁
                    Wounded.removeSelf();
                    Wounded.destroy(true); // true 表示销毁子节点（如果地形有的话）
                    this.showTip("地形已删除");

                    // 如果双击的是当前选中的地形，取消选中状态
                    if (this.selectedWounded === Wounded) {
                        this.selectedWounded = null;
                    }
                    // 如果恰好正在拖动这个地形（虽然不太可能，双击通常快于拖动结束），也取消拖动
                    if (this.draggingWounded === Wounded) {
                        this.draggingWounded = null;
                    }
                }
                break
            default:
                return; // 其他按键不处理
        }

        // 保存原始位置，以便移动失败时恢复
        const originalX = this.selectedWounded.x;
        const originalY = this.selectedWounded.y;
        console.log("newRow", newRow);
        console.log("newCol", newCol);
        // 计算新的屏幕坐标
        const newScreenPos = this.gridToScreen(newRow, newCol);

        // 清除当前占用的格子
        this.clearOccupiedGridsInState(this.selectedWounded);

        // 移动地形到新位置
        let offsetX = this.selectedWounded.width / 2 - this.selectedWounded.width * this.selectedWounded.anchorX + 25;
        this.selectedWounded.pos(newScreenPos.x, newScreenPos.y);
        console.log(newScreenPos.x, newScreenPos.y);
        // 检查新位置是否有效
        const isValid = this.checkAndUpdateWoundedGrids(this.selectedWounded, newScreenPos.x, newScreenPos.y);

        if (isValid) {
            // 更新地形的网格位置
            this.selectedWounded.posGrid = { row: newRow, col: newCol };
            // 更新z轴排序
            // this.selectedWounded.zOrder = newRow * 1000 + newCol;


            this.drawOccupiedGrids(this.selectedWounded)
            // 标记新位置的占用状态
            this.markOccupiedGridsInState(this.selectedWounded);
        } else {
            // 如果新位置无效，恢复到原始位置
            this.selectedWounded.pos(originalX, originalY);
            // 重新标记原始位置的占用状态
            this.checkAndUpdateWoundedGrids(this.selectedWounded, originalX, originalY);
            this.markOccupiedGridsInState(this.selectedWounded);
        }
    }

    /**
     * 当从地形列表选择一个地形时的处理函数
     * @param type 地形类型 (从 WoundedList 传递)
     * @param id 地形配置ID (从 WoundedList 传递)
     * @param icon 地形图标路径 (从 WoundedList 传递)
     */
    private onWoundedSelected(type: number, id: number, icon: string): void {
        console.log(`Wounded selected from list: type=${type}, id=${id}, icon=${icon}`);
        let WoundedConfig = WoundedConfigManager.getInstance().getWoundedConfig(id)
        const Wounded = this.createWounded(WoundedConfig);
        if (this.box_map) { // 确保地形容器存在
            this.addWoundedToMap(Wounded);
        } else {
            console.error("box_map is not assigned! Cannot add selected Wounded to map.");
            // 可能需要销毁创建的 Wounded 对象以防内存泄漏
            Wounded?.destroy(true);
        }
    }

    /**
     * 创建地形对象的实例并进行初始化设置
     * @param type 地形类型
     * @param id 地形ID
     * @param icon 地形图标资源路径
     * @returns 创建好的 Wounded 实例，或 null 如果失败
     */
    private createWounded(WoundedConfig: WoundedConfigItem): Wounded | null {
        try {
            const wounded = new Wounded(); // 实例化 Wounded 类
            // 调用初始化方法，传递必要的数据
            wounded.initWounded(WoundedConfig);

            // **重要**: 设置地形对象的锚点。等角对象通常建议锚点设在底部中心或中心。
            // 这会影响 pos(x, y) 的行为以及后续坐标计算。
            // 假设 Wounded 类内部处理了锚点，或者我们在这里统一设置：
            // Wounded.anchorX = 0.5; // 中心锚点
            // Wounded.anchorY = 0.5; // 中心锚点
            // 如果锚点是底部中心：
            // Wounded.anchorY = 1.0;

            return wounded;
        } catch (error) {
            console.error(`Failed to create Wounded instance (id: ${WoundedConfig.id}, icon: ${WoundedConfig.icon}):`, error);
            this.showTip("创建地形对象失败！");
            return null;
        }
    }

    /**
     * 将新创建或加载的地形添加到地图上，设置初始位置，并处理放置逻辑
     * @param wounded 要添加到地图的 Wounded 实例
     */
    private addWoundedToMap(wounded: Wounded): void {
        if (!this.box_map || !wounded) {
            console.error("Cannot add Wounded: box_map or Wounded instance is null.");
            return;
        }
        this.box_map.addChild(wounded); // 添加到地形层 (box_map)

        // 设定一个初始屏幕位置，例如地图中心或鼠标点击位置附近
        // 注意：pos(x, y) 设置的是锚点的位置
        const initialScreenX = 500
        const initialScreenY = 200

        // 将初始位置对齐到最近的格子中心
        const initialGridPos = this.sceneToGrid(initialScreenX, initialScreenY);

        wounded.pos(initialScreenX, initialScreenY); // 移动到找到的有效位置
        // 为成功放置的地形添加拖拽事件
        this.addWoundedDragEvents(wounded);
    }

    /**
     * 检查并更新地形占用的格子信息，并返回是否有效
     * @param wounded
     * @returns boolean 地形当前位置是否有效
     */
    private checkAndUpdateWoundedGrids(wounded: Wounded, posx: number, posy: number): boolean {
        if (!wounded || !wounded.updateOccupiedGrids) {
            console.error("Wounded object is invalid or missing 'updateOccupiedGrids' method.");
            return false;
        }
        // 调用 Wounded 实例的方法来计算和检查
        return wounded.updateOccupiedGrids(
            this.gridWidth,
            this.gridVisualHeight,
            posx, // 当前中心 x
            posy, // 当前中心 y
            this.localMapGrid, // 传递地图状态数组
            this.gridData, // 传递地图状态数组
            this.sceneToGrid.bind(this), // Pass the screenToGrid function bound to 'this'
            this.gridToScreen.bind(this)
        );
    }


    /**
     * 在 mapGrid 状态数组中标记地形占用的格子
     * @param wounded 地形对象，应包含其已计算好的 occupiedGrids 列表
     */
    private markOccupiedGridsInState(wounded: Wounded): void {
        if (!wounded || !wounded.occupiedGrids || wounded.occupiedGrids.length === 0) {
            // console.warn("Wounded has no occupiedGrids to mark state for.");
            return; // 没有要标记的格子
        }
        const WoundedIdToMark = wounded.type !== 0 ? wounded.type : -2; // 使用地形 type 或通用占用标记 (-2)
        // console.log(`Marking ${Wounded.occupiedGrids.length} grids in state for Wounded id ${Wounded.id} with value ${WoundedIdToMark}`);

        // 记录最大的行列坐标
        let maxRow = -1;
        let maxCol = -1;

        for (const grid of wounded.occupiedGrids) {
            // 更新最大坐标
            // maxRow = Math.max(maxRow, grid.row);
            if (maxRow < grid.row) {
                maxRow = grid.row
                maxCol = grid.col
            }
            // 再次检查边界，确保安全
            if (grid.row >= 0 && grid.row < this.gridData.length &&
                this.gridData[grid.row] && // 确保行存在
                grid.col >= 0 && grid.col < this.gridData[grid.row].length) {
                // 仅当格子当前为空(0)时标记，防止覆盖其他地形？或者允许覆盖？
                // 当前逻辑：直接覆盖，放置时 isWoundedPositionValid 会检查
                this.gridData[grid.row][grid.col].type = WoundedIdToMark;
            } else {
                console.warn(`Attempted to mark out-of-bounds grid state: ${grid.row}, ${grid.col} for Wounded ${wounded.id}`);
            }
        }

        // 设置地形的最大格子坐标
        if (maxRow !== -1 && maxCol !== -1) {
            // Wounded.maxGridPosition = { row: maxRow, col: maxCol };
            console.log("nax: ", maxRow, maxCol,)
            let pos = this.gridToScreen(maxRow, maxCol);
            // 根据新的锚点计算方式调整位置
            let offsetX = wounded.width / 2 - wounded.width & wounded.anchorX + 25
            wounded.pos(pos.x + offsetX, pos.y + 25);
            wounded.posGrid = { row: maxRow, col: maxCol };
            if (wounded.type === TerrainType.GRASS || wounded.type === TerrainType.ROAD || wounded.type === TerrainType.BRIDGE || wounded.type === TerrainType.PORTAL) {
                // 地面类型使用较小的倍数
                wounded.zOrder = maxCol * 5 + maxRow * 2;
            } else {
                // 建筑、树木等物体使用较大的倍数，但不要差距过大
                wounded.zOrder = maxCol * 100 + maxRow * 200 + 100;
            }
        }
        // Wounded.zOrder = Wounded.posGrid.row * 1000 + Wounded.posGrid.col;

    }

    /**
     * 在 mapGrid 状态数组中清除地形占用的格子，将其恢复为可通过状态 (0)
     * @param wounded 地形对象，需要其 occupiedGrids 列表
     */
    private clearOccupiedGridsInState(wounded: Wounded): void {
        if (!wounded || !wounded.occupiedGrids || wounded.occupiedGrids.length === 0) {
            // 可能在拖动开始时还没有计算好格子，或者地形本身没有占用格子
            // console.warn("Wounded has no occupiedGrids to clear state for.");
            return;
        }
        const WoundedMarkValue = wounded.type !== 0 ? wounded.type : -2;
        // console.log(`Clearing grid state for Wounded id ${Wounded.id} (value ${WoundedMarkValue})`);

        for (const grid of wounded.occupiedGrids) {
            // 边界检查
            if (grid.row >= 0 && grid.row < this.gridData.length &&
                this.gridData[grid.row] &&
                grid.col >= 0 && grid.col < this.gridData[grid.row].length) {
                // **重要**: 只清除由当前这个地形实例标记的格子
                // 避免错误地清除其他地形占用的格子
                if (this.gridData[grid.row][grid.col].type === WoundedMarkValue) {
                    this.box_game.getChildByName(`grid_mark_${grid.col}_${grid.row}`)?.destroy(true);
                    this.gridData[grid.row][grid.col].type = 0; // 恢复为可通过状态 (0)
                } else {
                    // 可能格子已经是 0，或者被其他东西占用了，不用处理
                }
            } else {
                console.warn(`Attempted to clear out-of-bounds grid state: ${grid.row}, ${grid.col} for Wounded ${wounded.id}`);
            }
        }
        // 清除后，地形实例内部的 occupiedGrids 列表也应该清空或置为无效，直到下次计算
        // Wounded.occupiedGrids = [];
    }

    /**
     * 初始化地图容器的事件监听（用于取消选中）和按钮事件
     */
    private initMapDragEvents(): void {
        // 导出按钮事件
        if (this.box_export) {
            this.box_export.on(Laya.Event.CLICK, this, this.exportMapConfig);
        } else { console.warn("Export button not assigned."); }

        // 加载/导入按钮事件
        if (this.box_load) {
            this.box_load.on(Laya.Event.CLICK, this, this.importMapConfig);
        } else { console.warn("Load button not assigned."); }

        // 地图容器本身的事件 (用于取消选中等)
        if (this.box_map) {
            // MOUSE_DOWN 用于检测点击地图背景
            this.box_map.on(Laya.Event.MOUSE_DOWN, this, this.onMapMouseDown);
        } else {
            console.error("box_map is null, cannot add map mouse down listener for deselection.");
        }

        // 舞台事件监听拖动和释放 (更可靠，因为鼠标可能移出地形或地图容器)
        Laya.stage.on(Laya.Event.MOUSE_MOVE, this, this.onStageMouseMove);
        Laya.stage.on(Laya.Event.MOUSE_UP, this, this.onStageMouseUp);
        // 当鼠标移出整个舞台区域时，也应该视为拖动结束
        Laya.stage.on(Laya.Event.MOUSE_OUT, this, this.onStageMouseUp);
        console.log("Map drag events initialized.");
    }

    /**
     * 为单个地形实例添加拖拽相关的事件监听器
     * @param wounded 要添加事件的地形对象
     */
    private addWoundedDragEvents(wounded: Wounded): void {
        if (!wounded) return;

        // --- 鼠标按下事件 (开始拖动) ---
        wounded._terrain.on(Laya.Event.MOUSE_DOWN, this, (e: Laya.Event) => {
            e.stopPropagation(); // 阻止事件冒泡到地图容器 (box_map)，避免触发取消选中
            this.draggingWounded = wounded;
            this.selectedWounded = wounded; // 同时设为选中状态

            // 计算鼠标按下位置相对于地形中心点(锚点)的偏移
            // this.offsetX = e.stageX - Wounded.x;
            // this.offsetY = e.stageY - Wounded.y;

            // 将当前拖动的地形提到渲染顶层，使其在其他地形之上
            if (this.box_map) {
                this.box_map.setChildIndex(wounded, this.box_map.numChildren - 1);
            }

            // **重要**: 在开始拖动时，清除该地形在 mapGrid 中的占用状态
            // 这样拖动过程中检查位置时，不会将自身视为障碍
            this.clearOccupiedGridsInState(wounded);

            // 可选: 添加视觉反馈，比如轻微放大或改变透明度，表示正在拖动
            // Wounded.scale(1.05, 1.05);
            // Wounded.alpha = 0.8;
            console.log(`Started dragging Wounded id: ${wounded.id}`);
        });

        // --- 鼠标抬起事件 (在地形自身上释放) ---
        // 如果在地形上抬起，也应该触发放置逻辑
        wounded._terrain.on(Laya.Event.MOUSE_UP, this, (e: Laya.Event) => {
            e.stopPropagation(); // 阻止冒泡到 stage 的 mouse up，避免重复处理
            this.handleWoundedDrop(e, e.stageX, e.stageY); // 使用通用的放置处理函数
        });

        // --- 双击事件 (删除地形) ---
        wounded._terrain.on(Laya.Event.DOUBLE_CLICK, this, (e: Laya.Event) => {
            e.stopPropagation(); // 阻止冒泡
            console.log(`Double clicked Wounded id: ${wounded.id}`);
            if (wounded.parent) { // 确保它还在场景中
                // 清除地图格子状态
                this.clearOccupiedGridsInState(wounded); // 确保清除的是最新的占用格子

                // 从父节点移除并销毁
                wounded.removeSelf();
                wounded.destroy(true); // true 表示销毁子节点（如果地形有的话）
                this.showTip("地形已删除");

                // 如果双击的是当前选中的地形，取消选中状态
                if (this.selectedWounded === wounded) {
                    this.selectedWounded = null;
                }
                // 如果恰好正在拖动这个地形（虽然不太可能，双击通常快于拖动结束），也取消拖动
                if (this.draggingWounded === wounded) {
                    this.draggingWounded = null;
                }
            }
        });
    }


    /**
     * 处理在地图背景容器 (box_map) 上按下鼠标的事件，通常用于取消选中
     * @param e 事件对象
     */
    private onMapMouseDown(e: Laya.Event): void {
        // 检查事件的目标是否确实是地图容器本身，而不是其子元素（如某个地形）
        if (e.target === this.box_map) {
            if (this.selectedWounded) {
                console.log("Clicked on map background, deselected Wounded.");
                // 可选：移除选中时的视觉效果（如边框）
                // if (this.selectedWounded.graphics) this.selectedWounded.graphics.clear();
            }
            this.selectedWounded = null; // 取消选中
        }
        // 注意：这里不阻止冒泡，以便舞台能接收到事件（如果需要的话）
    }

    /**
     * 处理在舞台 (Stage) 上移动鼠标的事件，用于更新拖动中地形的位置
     * @param e 事件对象
     */
    private onStageMouseMove(e: Laya.Event): void {
        if (this.draggingWounded) { // 检查是否真的在拖动一个地形
            // 计算地形的新中心点位置 (跟随鼠标，考虑初始偏移)
            const newX = e.stageX - this.offsetX;
            const newY = e.stageY - this.offsetY;

            // 直接更新地形的屏幕位置，让其视觉上跟随鼠标
            this.draggingWounded.pos(newX, newY);

            // **可选**: 实时显示放置指示器 (会影响性能)
            // this.showPlacementIndicator(this.draggingWounded);
        }
    }




    /**
     * 处理在舞台 (Stage) 上释放鼠标的事件，用于结束拖动并放置地形
     * @param e 事件对象
     */
    private onStageMouseUp(e: Laya.Event): void {
        // 检查是否是从拖动状态释放
        this.handleWoundedDrop(e, e.stageX, e.stageY); // 使用通用的放置处理函数
    }

    /**
     * 通用的处理地形放下/拖动结束的逻辑
     * @param finalStageX 鼠标最终的舞台 X 坐标
     * @param finalStageY 鼠标最终的舞台 Y 坐标
     */
    private handleWoundedDrop(evt: Laya.Event, finalStageX: number, finalStageY: number): void {
        if (this.draggingWounded) {
            const wounded = this.draggingWounded; // 本地引用，方便使用
            console.log(`Dropping Wounded id: ${wounded.id}`);

            // 恢复拖动时的视觉效果 (如果修改过)
            // Wounded.scale(1.0, 1.0);
            wounded.alpha = 1.0; // 恢复不透明
            // Wounded.graphics.clear(); // 清除临时的指示器边框等
            let finalX = evt.stageX - 50//this.buildShowView.x //+ this.buildShowView.width / 2
            let finalY = evt.stageY
            // 1. 计算最终的理论中心位置 (鼠标位置 - 初始偏移)
            // const finalX = finalStageX - this.offsetX;
            // const finalY = finalStageY - this.offsetY;
            console.log(finalX, finalY)
            wounded.pos(finalX, finalY);
            // return 

            // 2. 将理论位置对齐到最近的格子中心
            const targetGrid = this.sceneToGrid(finalX, finalY); // 找到目标格子
            const alignedPos = this.gridToScreen(targetGrid.row, targetGrid.col); // 获取该格子中心点

            // 3. 将地形的锚点移动到对齐后的格子中心位置
            // Wounded.pos(alignedPos.x, alignedPos.y);

            // 4. 检查对齐后的位置是否真的有效 (调用 checkAndUpdateWoundedGrids)
            const finalGridsValid = this.checkAndUpdateWoundedGrids(wounded, finalX, finalY);

            if (finalGridsValid) {
                // 5a. 位置有效: 最终确定位置，并在 mapGrid 中标记占用
                console.log(`Wounded id ${wounded.id} placed successfully at grid (${targetGrid.row}, ${targetGrid.col}).`);
                this.markOccupiedGridsInState(wounded); // 更新地图状态


                // 添加视觉标记
                this.drawOccupiedGrids(wounded);

            } else {
                // 5b. 位置无效: 尝试寻找附近最近的有效位置
                console.log(`Final aligned position (${targetGrid.row}, ${targetGrid.col}) is invalid. Attempting to find nearest valid spot...`);
                const validPos = this.findNearestValidPosition(wounded, wounded.x, wounded.y);

                // 检查找到的位置是否和当前无效位置不同 (避免死循环)
                wounded.pos(validPos.x, validPos.y); // 移动到建议位置
                const foundPosValid = this.checkAndUpdateWoundedGrids(wounded, validPos.x, validPos.y); // 再次检查

                if (foundPosValid && (validPos.x !== alignedPos.x || validPos.y !== alignedPos.y)) {
                    // 找到了一个不同的、有效的邻近位置
                    const foundGrid = this.screenToGridInOther(validPos.x, validPos.y);
                    this.showTip("位置冲突，已自动调整到最近可用位置");
                    console.log(`Wounded id ${wounded.id} moved to nearest valid grid (${foundGrid.row}, ${foundGrid.col}).`);
                    this.markOccupiedGridsInState(wounded); // 在新位置标记占用
                    // 在新位置添加视觉标记
                    this.drawOccupiedGrids(wounded);
                } else {
                    // 5c. 如果找不到有效位置，或者找到的位置还是无效/与原位相同，则放置失败
                    this.showTip("附近无可用位置，无法放置该地形");
                    console.log(`Failed to place Wounded id ${wounded.id}, no valid position found near (${targetGrid.row}, ${targetGrid.col}). Removing.`);
                    wounded.removeSelf(); // 从场景移除
                    wounded.destroy(true); // 销毁对象
                    // 如果放置失败的是当前选中的，取消选中
                    if (this.selectedWounded === wounded) this.selectedWounded = null;
                }
            }

            // 6. 无论成功与否，结束拖动状态
            this.draggingWounded = null;
            console.log("Dragging finished.");
            // 注意：selectedWounded 保持选中状态，除非放置失败或点击背景取消
        }
    }


    /**
    * 为地形占用的格子绘制视觉标记
    * @param wounded 要标记的地形对象
    */
    private drawOccupiedGrids(wounded: Wounded): void {
        // return
        if (!wounded || !wounded.occupiedGrids || wounded.occupiedGrids.length === 0) return;
        // 为每个占用的格子创建视觉标记
        let lineColor = "#000000"; // 默认格子线颜色 (浅灰色)
        //随机颜色
        // lineColor = "#" + Math.floor(Math.random()*16777215).toString(16);
        if (wounded.type === TerrainType.ROAD) {
            lineColor = "#cccccc"; // 默认格子线颜色 (浅灰色)
        }
        // 根据地形类型设置不同的颜色
        for (const grid of wounded.occupiedGrids) {
            const screenPos = this.gridToScreen(grid.row, grid.col);

            // 创建一个矩形标记
            const mark = new Laya.Sprite();
            mark.name = "grid_mark_" + grid.col + "_" + grid.row; // 用于后续清除

            mark.pos(screenPos.x, screenPos.y);
            // mark.alpha = 0.3; // 半透明

            const halfWidth = this.gridWidth / 2;
            const halfVisualHeight = this.gridVisualHeight / 2; // = 12.5

            // 定义菱形的顶点，相对于中心点 (0,0)
            // Y轴向下为正
            const diamondPoints = [
                0, -halfVisualHeight,    // Top vertex (中心点 Y - 半高)
                halfWidth, 0,              // Right vertex (中心点 X + 半宽)
                0, halfVisualHeight,     // Bottom vertex (中心点 Y + 半高)
                -halfWidth, 0               // Left vertex (中心点 X - 半宽)
            ];

            // **重要**: 使用 JSON 中的 x, y。这些是根据 Python 脚本逻辑计算好的单元格“逻辑原点”（在你的例子中是左上角）
            // 菱形的视觉中心点应该是 (逻辑原点x + 半宽, 逻辑原点y + 半高)
            const centerX = halfWidth;
            const centerY = halfVisualHeight; // 注意这里用的是 gridHeight (行间距)，正好是菱形高度的一半

            let lineWidth = 1;


            mark.graphics.drawPoly(centerX, centerY, diamondPoints, lineColor, lineColor, lineWidth);



            this.box_game.addChild(mark);
        }
    }



    /**
     * 检查地形在当前位置是否有效（所有占用的格子都必须是可通过的）
     * 实际的检查逻辑封装在 checkAndUpdateWoundedGrids 中
     * @param wounded 要检查的地形对象
     * @returns boolean 位置是否有效
     */
    private isWoundedPositionValid(wounded: Wounded): boolean {
        // 简单地调用封装好的检查方法
        return this.checkAndUpdateWoundedGrids(wounded, wounded.x, wounded.y);
    }


    /**
     * 当地形放置位置无效时，尝试在其周围寻找最近的一个有效格子中心点位置
     * @param wounded 要寻找位置的地形对象
     * @param startX 无效位置的 X 坐标 (中心点)
     * @param startY 无效位置的 Y 坐标 (中心点)
     * @returns 最近的有效位置 { x, y } (中心点坐标)，如果找不到则返回原始的 startX, startY
     */
    private findNearestValidPosition(wounded: Wounded, startX: number, startY: number): { x: number, y: number } {
        // 保存原始位置和格子状态，因为检查过程会临时修改它们
        const originalX = wounded.x;
        const originalY = wounded.y;
        const originalGrids = wounded.occupiedGrids ? [...wounded.occupiedGrids] : [];

        // 检查起始位置本身（虽然调用此函数时通常已知无效，但作为基础情况）
        wounded.pos(startX, startY);
        if (this.isWoundedPositionValid(wounded)) {
            wounded.pos(originalX, originalY); // 恢复
            wounded.occupiedGrids = originalGrids;
            return { x: startX, y: startY }; // 起始位置有效，直接返回
        }

        let minDistanceSq = Number.MAX_VALUE;
        let bestPosition = { x: startX, y: startY }; // 默认返回起始位置（如果找不到）
        let foundValid = false;

        const maxSearchRadius = 15; // 限制搜索半径（格子数），防止性能问题和搜索太远
        const startGrid = this.screenToGridInOther(startX, startY); // 起始格子

        // 从半径 1 开始，以菱形/曼哈顿距离方式向外扩展搜索
        for (let radius = 1; radius <= maxSearchRadius; radius++) {
            // 遍历当前半径圈上的所有格子
            for (let dr = -radius; dr <= radius; dr++) {
                const remainingDist = radius - Math.abs(dr);
                for (let dcSign = -1; dcSign <= 1; dcSign += 2) { // 处理正负列偏移
                    const dc = remainingDist * dcSign;
                    // 跳过半径为0的情况（dr=0, dc=0）以及重复计算（当 remainingDist=0 时 dc 会计算两次0）
                    if (dr === 0 && dc === 0) continue;
                    if (remainingDist === 0 && dcSign === 1) continue; // dc=0 已经被 dcSign=-1 处理过了

                    const testRow = startGrid.row + dr;
                    const testCol = startGrid.col + dc;

                    // 快速跳过无效格子坐标
                    if (testRow < 0 || testCol < 0 ||
                        testRow >= this.localMapGrid.length ||
                        !this.localMapGrid[testRow] ||
                        testCol >= this.localMapGrid[testRow].length) {
                        continue;
                    }

                    // 计算测试格子的中心屏幕坐标
                    const testPos = this.gridToScreen(testRow, testCol);

                    // 临时移动地形到测试位置并检查有效性
                    wounded.pos(testPos.x, testPos.y);
                    const isValid = this.isWoundedPositionValid(wounded); // isWoundedPositionValid 内部会调用 checkAndUpdateWoundedGrids

                    if (isValid) {
                        foundValid = true;
                        // 计算从原始无效点 (startX, startY) 到当前有效点 (testPos.x, testPos.y) 的距离平方
                        const distSq = Math.pow(testPos.x - startX, 2) + Math.pow(testPos.y - startY, 2);
                        if (distSq < minDistanceSq) {
                            minDistanceSq = distSq;
                            bestPosition = { x: testPos.x, y: testPos.y }; // 记录这个更好的有效位置
                        }
                    }
                }
            }
            // 如果在当前半径找到了至少一个有效位置，就可以停止搜索，因为我们要找的是最近的
            if (foundValid) {
                break; // 退出外层 radius 循环
            }
        }

        // 恢复地形到原始位置和状态
        wounded.pos(originalX, originalY);
        wounded.occupiedGrids = originalGrids;

        if (foundValid) {
            console.log(`Found nearest valid position at screen coords (${bestPosition.x.toFixed(1)}, ${bestPosition.y.toFixed(1)})`);
        } else {
            console.log("Could not find any valid position within search radius.");
        }

        return bestPosition; // 返回找到的最佳位置，或者原始位置（如果没找到）
    }


    /**
     * 导出当前地图配置为 JSON 文件
     */
    private exportMapConfig(): void {
        console.log("Exporting map configuration...");
        // 创建配置对象
        const config: any = {
            // A. 导出地图格子状态数据 (mapGrid)
            // 这记录了哪些格子是边界 (-1)，哪些是空的 (0)，哪些被占用了 (地形 type 或 -2)

        };

        // 遍历地形容器 (box_map) 中的所有子节点
        if (this.box_map) {
            for (let i = 0; i < this.box_map.numChildren; i++) {
                const child = this.box_map.getChildAt(i);
                if (child instanceof Wounded) { // 确保是 Wounded 实例
                    // 获取地形中心点所在的格子坐标
                    // const centerGrid = this.sceneToGrid(child.x, child.y); // 使用中心点坐标转换 
                    if (config[child.id] == null) {
                        config[child.id] = []
                    }

                    config[child.id].push({
                        row: child.posGrid.row,// 中心格子行
                        col: child.posGrid.col,// 中心格子列
                    });
                }
            }
            console.log(`Exporting ${config.length} Woundeds.`);
        } else {
            console.error("box_map is null, cannot export Woundeds.");
            this.showTip("错误：无法访问地形容器");
            return;
        }

        // 将配置对象转换为格式化的 JSON 字符串
        const configJson = JSON.stringify(config, null, 2); // 使用 2 个空格缩进，美化输出

        // 使用浏览器 API 创建并触发下载
        try {
            const blob = new Blob([configJson], { type: 'application/json;charset=utf-8' });
            const url = URL.createObjectURL(blob);
            const link = document.createElement('a');
            link.href = url;
            // 定义下载的文件名
            const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
            link.download = `wounded_${this.mapId}.json`;

            // 触发隐藏链接的点击事件来开始下载
            document.body.appendChild(link);
            link.click();

            // 清理：从文档移除链接并释放对象 URL
            document.body.removeChild(link);
            URL.revokeObjectURL(url);

            this.showTip("地图配置已成功导出");
            console.log("Map configuration exported successfully.");

        } catch (error) {
            console.error("导出地图配置失败:", error);
            this.showTip("导出失败，请查看控制台日志");
        }
    }

    /**
     * 导入地图配置文件 (JSON)，加载地图状态和地形
     */
    private async importMapConfig() {
        console.log("Import map configuration requested.");

        const input = document.createElement('input');
        input.type = 'file';
        input.accept = '.json';

        input.onchange = (e: Event) => {
            const target = e.target as HTMLInputElement;
            if (!target.files || !target.files[0]) return;

            const file = target.files[0];
            const reader = new FileReader();

            reader.onload = (e) => {
                try {
                    const config = JSON.parse(e.target?.result as string);

                    // 清除当前地图上的所有地形
                    this.clearAllWoundeds();

                    // 从 gridData 重建 mapGrid
                    if (config.mapGrid && Array.isArray(config.mapGrid)) {
                        //TODO
                        // this.gridData = config.mapGrid;

                        // // 初始化 mapGrid 二维数组
                        // const maxRow = this.gridData.length;//Math.max(...this.gridData.map(g => g.row)) + 1;
                        // const maxCol = this.gridData[0].length// Math.max(...this.gridData.map(g => g.column)) + 1;
                        // this.localMapGrid = this.gridData//Array(maxRow).fill(0).map(() => Array(maxCol).fill(0));


                    }

                    // 加载所有伤员
                    // 遍历JSON对象的每个键（伤员ID）
                    for (const woundedId in config) {
                        if (!config.hasOwnProperty(woundedId)) continue;

                        // 获取该ID下的所有伤员实例
                        const woundedInstances = config[woundedId];
                        if (!Array.isArray(woundedInstances)) continue;

                        // 获取伤员配置
                        const woundedData = WoundedConfigManager.getInstance().getWoundedConfig(parseInt(woundedId));
                        if (!woundedData) {
                            console.error(`未找到ID为 ${woundedId} 的伤员配置`);
                            continue;
                        }

                        // 遍历该类型的所有伤员实例
                        for (const instance of woundedInstances) {
                            const wounded = this.createWounded(woundedData);

                            if (this.box_map && wounded) {
                                // 设置位置
                                const screenPos = this.gridToScreen(instance.row, instance.col);
                                wounded.pos(screenPos.x, screenPos.y);

                                // 设置占用格子
                                wounded.occupiedGrids = [{ row: instance.row, col: instance.col}];
                                wounded.posGrid = { row: instance.row, col: instance.col };

                                // 标记占用状态并绘制
                                this.markOccupiedGridsInState(wounded);         
                                this.drawOccupiedGrids(wounded);

                                // 添加拖拽事件
                                this.addWoundedDragEvents(wounded);

                                // 设置Z轴排序
                                if (woundedData.type === TerrainType.GRASS ||
                                    woundedData.type === TerrainType.ROAD ||
                                    woundedData.type === TerrainType.BRIDGE ||
                                    woundedData.type === TerrainType.PORTAL) {
                                    wounded.zOrder = instance.row * 5 + instance.col * 2;
                                } else {
                                    wounded.zOrder = instance.row * 200 + instance.col * 100 + 100;
                                }

                                // 添加到地图
                                this.box_map.addChild(wounded);
                            }
                        }
                    }

                    this.showTip("地图配置加载成功");
                } catch (error) {
                    console.error("加载地图配置失败:", error);
                    this.showTip("地图配置加载失败");
                }
            };

            reader.readAsText(file);
        };

        input.click();
    }

    /**
     * 清除地图容器 (box_map) 中所有 Wounded 类型的子节点
     */
    private clearAllWoundeds(): void {
        if (!this.box_map) {
            console.warn("box_map is null, cannot clear Woundeds.");
            return;
        }
        console.log("Clearing all Woundeds from map container...");
        let clearedCount = 0;
        // 从后往前遍历并移除，这样更安全，不会因为移除导致索引变化而出错
        for (let i = this.box_map.numChildren - 1; i >= 0; i--) {
            const child = this.box_map.getChildAt(i);
            if (child instanceof Wounded) { // 只移除 Wounded 实例
                child.removeSelf(); // 从父节点移除
                child.destroy(true); // 彻底销毁对象及其子节点
                clearedCount++;
            }
        }
        // **重要**: 清除地形后，需要重置 mapGrid 中被它们占用的格子状态
        this.resetMapGridState();

        console.log(`Cleared ${clearedCount} Woundeds.`);
        // 重置选中和拖动状态
        this.selectedWounded = null;
        this.draggingWounded = null;
    }

    /**
     * 重置 mapGrid 状态数组，将所有非边界 (-1) 的格子恢复为可通过状态 (0)
     */
    private resetMapGridState(): void {
        console.log("Resetting mapGrid state...");
        if (!this.gridData || this.gridData.length === 0) {
            console.warn("mapGrid is empty, cannot reset state.");
            return;
        }
        let resetCount = 0;
        for (let r = 0; r < this.gridData.length; r++) {
            if (!this.gridData[r]) continue;
            for (let c = 0; c < this.gridData[r].length; c++) {
                // 只重置非边界格子
                if (this.gridData[r][c].type !== -1) {
                    if (this.gridData[r][c].type !== 0) resetCount++; // 统计被重置的格子数
                    this.gridData[r][c].type = 0; // 设为可通过 (0)
                }
            }
        }
        console.log(`mapGrid state reset. ${resetCount} cells set to 0 (passable).`);
    }

    /**
     * 在屏幕上显示一个短暂的提示信息
     * @param message 要显示的消息文本
     */
    private showTip(message: string): void {
        // 移除可能存在的上一个提示，避免重叠
        const oldTip = Laya.stage.getChildByName("globalTip") as Laya.Label;
        if (oldTip) {
            Laya.timer.clear(this, oldTip.removeSelf); // 清除旧提示的移除计时器
            oldTip.removeSelf(); // 立即移除旧提示
        }

        // 创建新的 Label 作为提示
        const tip = new Laya.Label();
        tip.name = "globalTip"; // 给提示命名，方便查找和移除
        tip.text = message;
        tip.fontSize = 24; // 设置合适的字体大小
        tip.color = "#ffffff"; // 白色文字
        tip.bgColor = "#000000cc"; // 半透明黑色背景，增加可读性
        tip.padding = "10,15,10,15"; // 设置内边距，让文字不贴边
        tip.anchorX = 0.5; // 设置锚点为中心，方便定位
        tip.anchorY = 0.5;
        // 定位到舞台顶部中间
        tip.pos(Laya.stage.width / 2, Laya.stage.height * 0.1);
        tip.zOrder = 10000; // 设置一个较高的 Z 轴顺序，确保在最上层显示

        Laya.stage.addChild(tip); // 将提示添加到舞台

        // 设置一个定时器，在 2 秒后自动移除提示
        Laya.timer.once(2000, this, () => {
            if (tip.parent) { // 检查提示是否还存在于舞台上
                tip.removeSelf(); // 从舞台移除
            }
            // LayaAir 会自动进行垃圾回收，通常不需要手动调用 tip.destroy()
        });
    }


    /**
     * 组件销毁时执行，用于清理事件监听器和定时器
     */
    onDestroy(): void {
        console.log("WoundedScript onDestroy called. Cleaning up listeners and timers.");

        // 移除添加到舞台的事件监听器
        Laya.stage.off(Laya.Event.MOUSE_MOVE, this, this.onStageMouseMove);
        Laya.stage.off(Laya.Event.MOUSE_UP, this, this.onStageMouseUp);
        Laya.stage.off(Laya.Event.MOUSE_OUT, this, this.onStageMouseUp);

        // 移除添加到地图容器的事件监听器
        if (this.box_map) {
            this.box_map.off(Laya.Event.MOUSE_DOWN, this, this.onMapMouseDown);
        }

        // 移除地形列表的事件监听
        if (this.woundedList) {
            this.woundedList.off('WoundedSelected', this, this.onWoundedSelected);
            // 如果 WoundedList 是 Laya.Script 或自定义组件，可能也需要调用其 destroy 方法
            // this.WoundedList.destroy();
        }

        // 移除按钮的事件监听
        this.box_export?.off(Laya.Event.CLICK, this, this.exportMapConfig);
        this.box_load?.off(Laya.Event.CLICK, this, this.importMapConfig);

        // 清理所有与此对象关联的 Laya.timer 定时器
        Laya.timer.clearAll(this);

        // 其他可能的清理，例如取消网络请求等

        console.log("WoundedScript cleanup complete.");
    }

} // End of WoundedScript class